{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# <center>RegEx in Python</center>\n",
    "\n",
    "![](images/memes/meme23.jpg)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Grouping\n",
    "\n",
    "> Frequently you need to obtain more information than just whether the regex pattern matched or not.\n",
    "\n",
    "By placing part of a regular expression inside round brackets or parentheses `(`, `)`, you can **group that part** of the regex pattern together.\n",
    "\n",
    "### Applications of grouping:\n",
    "\n",
    "#### 1. apply a quantifier to the entire group.\n",
    "\n",
    "For example, `(ab)+` will match one or more repetitions of `ab`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import re\n",
    "from utils import highlight_regex_matches"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "txt = \"abbbbbabbbb\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "pattern1 = re.compile(\"ab+\")\n",
    "pattern2 = re.compile(\"(ab)+\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[43m\u001b[1mabbbbb\u001b[0m\u001b[43m\u001b[1mabbbb\u001b[0m\n"
     ]
    }
   ],
   "source": [
    "highlight_regex_matches(pattern1, txt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[43m\u001b[1mab\u001b[0mbbbb\u001b[43m\u001b[1mab\u001b[0mbbb\n"
     ]
    }
   ],
   "source": [
    "highlight_regex_matches(pattern2, txt)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2. restrict alternation to part of the regex.\n",
    "\n",
    "For example, `my name is ram|sam` will match `my name is ram` and `sam` whereas `my name is (ram|sam)` will match `my name is ram` and `my name is sam`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "txt = \"\"\"\n",
    "my name is ram\n",
    "my name is sam\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "pattern1 = re.compile(\"my name is ram|sam\")\n",
    "pattern2 = re.compile(\"my name is (ram|sam)\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\u001b[43m\u001b[1mmy name is ram\u001b[0m\n",
      "my name is \u001b[43m\u001b[1msam\u001b[0m\n",
      "\n"
     ]
    }
   ],
   "source": [
    "highlight_regex_matches(pattern1, txt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\u001b[43m\u001b[1mmy name is ram\u001b[0m\n",
      "\u001b[43m\u001b[1mmy name is sam\u001b[0m\n",
      "\n"
     ]
    }
   ],
   "source": [
    "highlight_regex_matches(pattern2, txt)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 3. capture the text matched by group.\n",
    "\n",
    "- Groups indicated with `(`, `)` also capture the **starting** and **ending** index of the text that they match.\n",
    "\n",
    "- Groups can be retrieved by passing an argument to `group()`, `start()`, `end()`, and `span()` of the `Match` object. \n",
    "\n",
    "- Groups are numbered starting with `0`. \n",
    "\n",
    "- Group `0` is always present; it captures the whole regex pattern, so all `Match` object methods have group `0` as their default argument.\n",
    "\n",
    "Consider an example where we want to parse a date and determine day, month and year."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "txt = \"12/02/2019\" "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "pattern = re.compile(\"(\\d{2})\\/(\\d{2})\\/(\\d{4})\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "match = pattern.match(txt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'12/02/2019'"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# group 0: matches entire regex pattern\n",
    "match.group(0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'12'"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# group 1: match 1st group\n",
    "match.group(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'02'"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "match.group(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'2019'"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "match.group(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "day, month, year = match.groups()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('12', '02', '2019')"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "day, month, year"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's try one more example of group capturing. \n",
    "\n",
    "In the given text, find all the patterns with `Name: <some-name>` and extract `<some-name>`. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "txt = \"\"\"\n",
    "Name: Nikhil\n",
    "Age: 0\n",
    "Roll No.: 15\n",
    "Grade: S\n",
    "\n",
    "Name: Ravi\n",
    "Age: -1\n",
    "Roll No.: 123\n",
    "Grade: K\n",
    "\n",
    "Name: Ram\n",
    "Age: N/A\n",
    "Roll No.: 1\n",
    "Grade: G\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "pattern = re.compile(\"Name: (.+)\\n\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Nikhil', 'Ravi', 'Ram']"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pattern.findall(txt)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> Parentheses cannot be used inside character classes, at least not as metacharacters. When you put a parenthesis in a character class, it is treated as a literal character. So the regex `[(a)b]` matches `a`, `b`, `(`, and `)`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![](images/memes/meme24.jpg)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
